package br.com.tarcilahelpdesk.util;

import br.com.tarcilahelpdesk.persistencia.ObjetoPersistente;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.persistence.Query;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;

/**
 * 
 * @author vinicius
 */
public class PFDataModel extends LazyDataModel<ObjetoPersistente>
{

    private DAOGenerico dao;
    private Collection<Criterion> listaCriterions;
    private ProjectionList listaProjections;
    private Class clazz;
    private String hql;
    private Session ss;

    public PFDataModel(Class clazz, Session ss, DAOGenerico dao)
    {
        this.clazz = clazz;
        this.ss = ss;
        this.dao = dao;
    }

    public PFDataModel(Class clazz, DAOGenerico dao, String hql, Session ss)
    {
        this.clazz = clazz;
        this.ss = ss;
        this.dao = dao;
        this.hql = hql;
    }

    public PFDataModel(Class clazz, DAOGenerico dao, Collection<Criterion> lista, ProjectionList listaProj, Session ss)
    {
        this.clazz = clazz;
        this.ss = ss;
        this.dao = dao;
        this.listaCriterions = lista;
        this.listaProjections = listaProj;
    }

    @Override
    public ObjetoPersistente getRowData(String rowKey)
    {
        ObjetoPersistente objeto = (ObjetoPersistente) dao.buscarPorID(Long.parseLong(rowKey), ss);
        return objeto;
    }

    @Override
    public String getRowKey(ObjetoPersistente objeto)
    {
        return objeto.getId().toString();
    }

    @Override
    public List<ObjetoPersistente> load(int paginaInicial, int qtdePorPagina, String campoParaOrdenar, SortOrder so, Map filtros)
    {

        try
        {
            Criteria crit = ss.createCriteria(clazz);

            //Enquanto existir valores na lista de restrictions, adiciona na consulta.
            if (listaCriterions != null && !listaCriterions.isEmpty())
            {
                for (Iterator<Criterion> it = listaCriterions.iterator(); it.hasNext();)
                {
                    Criterion criterion = it.next();
                    crit.add(criterion);
                }

            }

            if (listaProjections != null)
            {
                crit.setProjection(listaProjections);
            }


            //Filtro
            for (Iterator<String> it = filtros.keySet().iterator(); it.hasNext();)
            {
                String campoFiltrado = it.next();
                String valorDoFiltro = (String) filtros.get(campoFiltrado);
                crit.add(Restrictions.ilike(campoFiltrado, valorDoFiltro, MatchMode.ANYWHERE));
            }

            crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

            setRowCount(crit.list().size());

            //Ordenacao
            if (campoParaOrdenar != null)
            {
                if (so == SortOrder.ASCENDING)
                {
                    crit.addOrder(Order.asc(campoParaOrdenar));
                }
                else
                {
                    crit.addOrder(Order.desc(campoParaOrdenar));
                }
            }

            //Paginacão
            crit.setFirstResult(paginaInicial);
            crit.setMaxResults(qtdePorPagina);

            return crit.list();
        }
        catch (RuntimeException e)
        {
            throw e;
        }
    }
}
